package io.gitee.cengxiaoxiao.wrapper;

import cn.idev.excel.ExcelWriter;
import cn.idev.excel.FastExcel;
import cn.idev.excel.FastExcelFactory;
import cn.idev.excel.converters.localdate.LocalDateStringConverter;
import cn.idev.excel.converters.localdatetime.LocalDateTimeStringConverter;
import cn.idev.excel.enums.WriteDirectionEnum;
import cn.idev.excel.support.ExcelTypeEnum;
import cn.idev.excel.util.StringUtils;
import cn.idev.excel.write.builder.ExcelWriterBuilder;
import cn.idev.excel.write.metadata.WriteSheet;
import cn.idev.excel.write.metadata.fill.FillConfig;
import cn.idev.excel.write.metadata.fill.FillWrapper;
import io.gitee.cengxiaoxiao.converters.LocalTimeConverter;
import io.gitee.cengxiaoxiao.exceptions.ExcelException;
import io.gitee.cengxiaoxiao.tools.ExcelUtil;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

public class ExcelFillWrapper {

    private static final ExcelWriterBuilder BaseBuilder = FastExcelFactory.write()
            .charset(StandardCharsets.UTF_8)
            .autoCloseStream(true)
            .registerConverter(LocalTimeConverter.INSTANCE())
            .registerConverter(new LocalDateStringConverter())
            .registerConverter(new LocalDateTimeStringConverter());


    /**
     * 组合填充数据,多个列表填充到同一个模板
     *
     * @param template 模板文件
     * @param data     数据
     * @return 输出流
     */
    public static byte[] compositeFill(InputStream template, Map<String, Collection<?>> data) {
        if (template == null) {
            throw new IllegalArgumentException("模板不能为空");
        }
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("数据不能为空");
        }
        ExcelWriterBuilder builder = BaseBuilder.withTemplate(template)
                .autoCloseStream(true);
        try (ExcelWriter excelWriter = builder.build()) {
            WriteSheet writeSheet = FastExcel.writerSheet().build();
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            for (Map.Entry<String, Collection<?>> entry : data.entrySet()) {
                Collection<?> collection = entry.getValue();
                if (collection == null || collection.isEmpty()) {
                    continue;
                }
                excelWriter.fill(new FillWrapper(entry.getKey(), collection), writeSheet);
            }
            return bos.toByteArray();
        } catch (Exception e) {
            throw new ExcelException(e);
        }
    }

    /**
     * 填充数据到Excel模板，水平方向
     *
     * @param os           输出流
     * @param data         数据
     * @param templatePath 模板路径
     * @param <T>          数据类型
     */
    public static <T> void fillHorizontal(OutputStream os, Collection<T> data, String templatePath) {
        FillConfig fillConfig = FillConfig.builder()
                .direction(WriteDirectionEnum.HORIZONTAL)
                .build();
        fill(os, data, templatePath, fillConfig);
    }

    public static <T> void fill(OutputStream os, T data, String templatePath) {
        fill(os, Collections.singleton(data), templatePath);
    }

    public static <T> void fill(OutputStream os, Collection<T> data, String templatePath) {
        fill(os, data, templatePath, null);
    }

    public static <T> void fill(OutputStream os, Collection<T> data, String templatePath, FillConfig fillConfig) {
        if (StringUtils.isBlank(templatePath)) {
            throw new IllegalArgumentException("模板路径不能为空");
        }
        ExcelUtil.isExcel(templatePath);
        File file = new File(templatePath);
        if (!file.exists()) {
            throw new IllegalArgumentException("模板文件不存在");
        }
        try (FileInputStream inputStream = new FileInputStream(file)) {
            fill(os, data, inputStream, fillConfig);
        } catch (IOException e) {
            throw new ExcelException(e);
        }
    }

    public static <T> void fill(OutputStream os, Collection<T> data, InputStream template) {
        fill(os, data, template, null);
    }

    public static <T> void fill(OutputStream os, Collection<T> data, InputStream template, FillConfig fillConfig) {
        if (os == null) {
            throw new IllegalArgumentException("OutputStream不能为空");
        }
        if (template == null) {
            throw new IllegalArgumentException("模板不能为空");
        }
        ExcelWriterBuilder builder = BaseBuilder.file(os)
                .withTemplate(template)
                .excelType(ExcelTypeEnum.XLSX);
        // 写数据
        try (ExcelWriter excelWriter = builder.build()) {
            WriteSheet writeSheet = FastExcel.writerSheet().build();
            if (fillConfig != null) {
                excelWriter.fill(data, fillConfig, writeSheet);
            } else {
                excelWriter.fill(data, writeSheet);
            }
        } catch (Exception e) {
            throw new ExcelException(e);
        }
    }
}
